const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`;
const qnameCapture = `((?:${ncname}\\:)?${ncname})`;
const startTagOpen = new RegExp(`^<${qnameCapture}`); //匹配一个开始的标签名 <div>
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`); //匹配一个结束的标签名 </div>
const attribute =
  /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>']+)))?/; //匹配标签属性
const startTagClose = /^\s*(\/?)>/; //<br/>
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g; //{{}}

export function parseHTML(html) {
  // 利用栈型结构 构建树
  const ELEMENT_TYPE = 1
  const TEXT_TYPE = 3
  const stack = [] //用于存放元素
  let currentParent //指向栈中的最后一个
  let root
  // 创造ast语法树
  function createASTElement(tag,attrs) {
    return {
      tag,
      type:ELEMENT_TYPE,
      children:[],
      attrs,
      parent:null
    }
  }
  function start(tag,attrs) {
    let node = createASTElement(tag,attrs) //创造一个ast节点
    if (!root) { //看一下是否空树
      root = node //如果为空则当前是树的根节点
    }
    if (currentParent) {
      node.parent = currentParent;
      currentParent.children.push(node)
    }
    stack.push(node)
    currentParent = node
  }
  function chars(text) {
    text = text.replace(/\s/g,'')
    text && currentParent.children.push({
      type:TEXT_TYPE,
      text,
      parent:currentParent
    })

  }
  function end() {
    stack.pop()    
    currentParent = stack[stack.length-1]
  }
  function advance(n) {
    html = html.substring(n);
  }
  function parseStartTag() {
    const start = html.match(startTagOpen);
    if (start) {
      const match = {
        tagName: start[1], //标签名
        attrs: [],
      };
      advance(start[0].length);
      let attr, end;
      while (
        !(end = html.match(startTagClose)) &&
        (attr = html.match(attribute))
      ) {
        advance(attr[0].length);
        match.attrs.push({
          name: attr[1],
          value: attr[3] || attr[4] || attr[5] || true,
        });
      }
      if (end) {
        advance(end[0].length);
      }
      // console.log(match);
      return match;
    }

    return false; //不是开始标签
  }
  while (html) {
    let textEnd = html.indexOf("<");
    if (textEnd === 0) {
      const startTagMatch = parseStartTag();

      if (startTagMatch) { //解析到的开始标签
        start(startTagMatch.tagName,startTagMatch.attrs)
        continue
      }
      let endTagMatch = html.match(endTag)
      if (endTagMatch) {
        advance(endTagMatch[0].length)
        end(endTagMatch[1])
        continue
      }
    }
    if (textEnd>0) {
      let text =  html.substring(0,textEnd) //文本内容
      if (text) {
        chars(text)
        advance(text.length)
      }
    }
  }
  return root
}